<?php
/*
 * Created on Jan 27, 2008
 *
 * This is an open source software, please obey the GPL
 * The Referee Service is offered by Cacomand Inc. 
 * View Http://www.cacomand.com for support or more information
 * You can also view distrema.googlecode.com to join the community.
 */

/*
 * This file is the foundamantal file of the DistRema,which include the
 * dps_user class as a basic unit of a service
 * This file also include a link to the dps
 */
 
include("lib_user.php");
include("open_dps_link.php");

/******************************************************************************
  * Get the epsn of the browser user from the cookie.
  * We use cookie alone to build the user authorizing
  * system without the session,because cookies can remaind
  * longer. Thus user would not be asked to input their username
  * and password until they log out.
  *
  * Returns epsn on success, false on error.
  *
  * usage: get_current_epsn()
  *
  * @access    public
  * @return    string
  * @see       get_current_user_ID
  */
function get_current_epsn()
{
	if(isset($_COOKIE["DistRema_epsn"]))
		return $_COOKIE["DistRema_epsn"];
	return false;
}

/******************************************************************************
  * Get the user ID of the browser user from the cookie.
  *
  * Returns user ID on success, false on error.
  *
  * usage: get_current_user_ID()
  *
  * @access    public
  * @return    integer
  * @see       get_current_epsn
  */
function get_current_user_ID()
{
	if(isset( $_COOKIE["DistRema_user_ID"]))
		return $_COOKIE["DistRema_user_ID"];
	return false;
}

/******************************************************************************
  * Create the user object of the browser user from the cookie.
  *
  * Returns an user object on success, false on error.
  *
  * usage: get_current_user_obj()
  *
  * @access    public
  * @return    integer
  * @see       get_current_epsn
  * @see       get_current_user_ID
  */
function get_current_user_obj()
{
	$to_return=false;
	if(get_current_epsn() AND get_current_user_ID() AND $now_user=new dps_user(get_current_epsn(),get_current_user_ID()))
		$to_return=$now_user;
	return $to_return;
}

/******************************************************************************
  * Determine whether an user is loged in.
  *
  * Returns true on loged in, false on error or not logedin.
  *
  * usage: islogedin()
  *
  * @access    public
  * @return    boolean
  */
function islogedin()
{
	global $developer;
	$login=false;
	if(isset($_COOKIE["DistRema_epsn"]) and isset($_COOKIE["DistRema_user_ID"]))
	{
		if($developer)
			echo("User loged in:".$username."<br />");
		$login=true;
	}
	return $login;
}

/******************************************************************************
  * Get the default caption for this type of variables from the REF.
  *
  * Returns default caption on success, false on error.
  *
  * usage: get_default_caption(string $var_ID)
  *
  * @param     integer $var_ID		   var type
  * @access    public
  * @return    string
  * @see       get_default_memo
  */
function get_default_caption($var_ID)
{
		//global $ref_host,$ref_basename,$ref_username,$ref_password;
		global $ref_link;
		global $developer;
		/**$ref_link=mysql_connect($ref_host,$ref_username,$ref_password);
		mysql_select_db($ref_basename,$ref_link);*/
		if ($ref_link!=FALSE)
		{
			$select_format='SELECT default_caption FROM vartype_pool WHERE var_ID=%d';
			$query=sprintf($select_format,$var_ID);
			if($developer)
				echo("获得默认索引".$query."<br />");
			$res_var_dc=mysql_query($query,$ref_link);
			//mysql_close($ref_link);
			if($obj_var_dc=mysql_fetch_object($res_var_dc))
			{
				if($developer)
					echo("获得了默认索引:".$obj_var_dc->default_caption."<br />");
				return $obj_var_dc->default_caption;
			}
			else
			{
				if($developer)
					echo("获取默认索引:变量类型".$var_ID."的默认索引未定义<br />");
				return false;
			}
		}
}

/******************************************************************************
  * Get the default memo for this type of variables from the REF.
  *
  * Returns default memo on success, false on error.
  *
  * usage: get_default_memo(string $var_ID)
  *
  * @param     integer $var_ID		   var type
  * @access    public
  * @return    string
  * @see       get_default_caption
  */
function get_default_memo($var_ID)
{
		//global $ref_host,$ref_basename,$ref_username,$ref_password;
		global $ref_link;
		global $developer;
		/**$ref_link=mysql_connect($ref_host,$ref_username,$ref_password);
		mysql_select_db($ref_basename,$ref_link);*/	
		if ($ref_link!=FALSE)
		{
			$select_format='SELECT default_memo FROM vartype_pool WHERE var_ID=%d';
			$query=sprintf($select_format,$var_ID);
			if($developer)
				echo("获取默认内容".$query."<br />");
			$res_var_dm=mysql_query($query,$ref_link);
			//mysql_close($ref_link);
			if($obj_var_dm=mysql_fetch_object($res_var_dm))
			{
				if($developer)
					echo("获取默认内容:获得了默认内容:".$obj_var_dm->default_memo."<br />");
				return $obj_var_dm->default_memo;
			}
			else
			{
				if($developer)
					echo("获取默认内容:变量".$var_ID."的默认内容尚未定义<br />");
				return false;
			}
		}
}

/******************************************************************************
  * Send data between users.The data will be stored in the sent_data_pool 
  * which can be deleted by anyone
  *
  * Returns true on success, false on error.
  *
  * usage: send_data(object $sender,object $receiver,integer $var_ID,string $caption,string $memo)
  *
  * @param     object $sender		   user object which to sand data from 
  * @param     object $receiver	   user object which to sand data to
  * @param     integer $var_ID		   sending data's var type
  * @param     string $caption		   deleting record's caption
  * @param     string $memo			   deleting record's memo
  * @access    public
  * @return    boolean
  * @see       delete_data
  */
function send_data($sender,$receiver,$var_ID,$caption,$memo)
{
	global $ccr_public_username,$ccr_public_key,$ccr_basename;
	global $developer;
	$ccr_link=mysql_connect($receiver->ccr_host,$ccr_public_username,$ccr_public_key);//this link must be outside the class
	mysql_select_db($ccr_basename,$ccr_link);
	if($ccr_link!=FALSE)
	{
		$select_format='SELECT rec_ID FROM sent_data_pool WHERE user_ID=%d AND var_ID=%d AND caption="%s" AND memo="%s"';
		$query=sprintf($select_format,$receiver->user_ID,$var_ID,$caption,$memo);
		if($developer)
			echo("".$query."<br />");
		$res_tocheck=mysql_query($query,$ccr_link);
		if($obj_tocheck=mysql_fetch_object($res_tocheck))
			return true;
		else
		{
		$insert_format='INSERT INTO sent_data_pool (user_ID,var_ID,caption,memo) VALUE (%d,%d,"%s","%s")';
		$query=sprintf($insert_format,$receiver->user_ID,$var_ID,$caption,$memo);
		if($developer)
			echo("发送信息:".$query."<br />");
		$res_nouse=mysql_query($query,$ccr_link);
		$rec_ID=mysql_insert_id($ccr_link);
		
		$insert_format='INSERT INTO sender_log (sender_name,sender_epsn,sender_user_ID,rec_ID,send_date) VALUE ("%s","%s",%d,%d,"%s")';
		$query=sprintf($insert_format,$sender->username,$sender->epsn,$sender->user_ID,$rec_ID,date("Y/m/d/G/i/s"));
		if($developer)
			echo("发送信息:".$query."<br />");
		$res_nouse=mysql_query($query,$ccr_link);
		//mysql_close($ccr_link);
		return true;
		}
	}
	return false;		
}//end of function send_data

/******************************************************************************
  * Delete the data identified by var ID from the sent data pool.
  *
  * Returns true on success, false on error.
  *
  * usage: delete_data(object $receiver,integer $var_ID,string $caption,string $memo)
  *
  * @param     object $receiver	   user object which to delete data from
  * @param     object $var_ID	   deleting data's var type
  * @param     string $caption	   deleting record's caption
  * @param     string $memo		   deleting record's memo
  * @access    public
  * @return    boolean
  * @see       sent_data
  */
function delete_data($receiver,$var_ID,$caption,$memo)
{
	global $ccr_public_username,$ccr_public_key,$ccr_basename;
	global $developer;
	$ccr_link=mysql_connect($receiver->ccr_host,$ccr_public_username,$ccr_public_key);//this link must be outside the class
	mysql_select_db($ccr_basename,$ccr_link);
	if($ccr_link!=FALSE)
	{
		$delete_format='DELETE FROM sent_data_pool WHERE var_ID=%d AND user_ID=%d AND caption="%s" AND memo="%s"';
		$query=sprintf($delete_format,$var_ID,$receiver->user_ID,$caption,$memo);
		if($developer)
			echo("删除信息：".$query."<br />");
		$res_nouse=mysql_query($query,$ccr_link);
		//mysql_close($ccr_link);
		return true;
	}
	return false;
}

/******************************************************************************
  * A small tool to determine the period time of the server.
  *
  * Returns period name on success, false on error.
  *
  * usage: get_term()
  *
  * @access    public
  * @return    string
  */
function get_term()
{
	$now_hour=date("G")+8;
	if($now_hour>=3 and $now_hour<12)
	{
		$daytime="morning";
	}
	elseif($now_hour>=12 and $now_hour<18)
	{
		$daytime="afternoon";
	}
	else
	{
		$daytime="evening";
	}
	return $daytime;
}

/******************************************************************************
  * Log in using epsn and user_ID.During which the function will try to get the
  * username to check if the epsn and user ID are legal
  *
  * Returns true on success, false on error.
  *
  * usage: user_login(string $epsn,integer $user_ID)
  *
  * @param     string $epsn      	 epsn of the user's CCR
  * @param     string $user ID       the user's user ID on his CCR 
  * @access    public
  * @return    boolean
  * @see       ccr_user_login
  */
function user_login($epsn,$user_ID)
{
	global $developer;
	if(isset($_COOKIE["DistRema_epsn"]) and isset($_COOKIE["DistRema_user_ID"]))
	{
		return true;
	}
	elseif(!empty($epsn) and !empty($user_ID))
	{
		$username=get_username($_POST["post_epsn"],$_POST["post_user_ID"]);
		if($username==false)
		{
			return false;
		}
		else
		{
			setcookie("DistRema_epsn", $_POST["post_epsn"], time() + (3600*24));
			setcookie("DistRema_user_ID", $_POST["post_user_ID"], time() + (3600*24)); 
			return true;
		}
	}
	else
	{
		return false;
	}
}

/******************************************************************************
  * Log in using username and password.If the u/p is legal(checking the md5 code)
  * the funtion will submit a confirm request automatically
  *
  * Returns 0,on unknown error,1 on epsn not exist,2 on username not exist,3 on password wrong, 4 on login succeed
  *
  * usage: ccr_user_login(string $username,string $password)
  *
  * @param     string $username       the user's username
  * @param     string $password       the user's password  
  * @access    public
  * @return    integer
  * @see       user_login
  */
function ccr_user_login($username,$password)
{
global $ccr_public_username,$ccr_public_key,$ccr_basename;
global $developer;
global $default_ccr_host,$default_ccr_epsn;
if(func_num_args()==3)
{
	$ccr_epsn=func_get_arg(2);
	$ccr_host=get_ccr_host($ccr_epsn);
	if($ccr_host==false)
	{
		return "1";
	}
}	
else
{
	$ccr_epsn=$default_ccr_epsn;
	$ccr_host=$default_ccr_host;
}
if(isset($ccr_link))
	mysql_close($ccr_link);//close the previous ccr link which may not be link to the same ccr
$ccr_link=mysql_connect($ccr_host,$ccr_public_username,$ccr_public_key);
mysql_select_db($ccr_basename,$ccr_link);
if($ccr_link!=FALSE)
{
	$select_format='SELECT user_ID,password FROM user_list WHERE username="%s"';
	$query=sprintf($select_format,$username);
	if($developer)
		echo("".$query."<br />");
	$res_password=mysql_query($query,$ccr_link);
	if($obj_password=mysql_fetch_object($res_password))
	{
		if(md5($password)==$obj_password->password)
		{
			setcookie("DistRema_epsn",$ccr_epsn, time() + (3600*24));
			setcookie("DistRema_user_ID",$obj_password->user_ID, time() + (3600*24));
			$login_user=new dps_user($ccr_epsn,$obj_password->user_ID);
			$login_user->confirm_upload($password); 
			return "4";
		}
		else
		{
			return "3";
		}
	}
	else
	{
		return "2";
	}
}
else
{
	return "1";
}
}

function deal_with_confirm()
{
	$checker=get_current_user_obj();
	if(func_num_args()==1)
		$default_service=func_get_arg(0);
	if($_POST["submit"]=="删除这些更新")
	{
		
		global $dps_link;
		global $developer;
		
		if($dps_link!=FALSE)
		{
			foreach($_POST["ul_todel"] as $ul_ID)
			{
				$delete_format='DELETE FROM upload_cache WHERE ul_ID=%d AND epsn=%d AND user_ID=%d';
				$query=sprintf($delete_format,$ul_ID,$checker->epsn,$checker->user_ID);
				if($developer)
				echo($query."<br />");
				$res_nouse=mysql_query($query,$dps_link);
			}
			//mysql_close($dps_link);
		}			
	}
	elseif($_POST["submit"]=="提交全部更新")
	{
		if($_POST["password"]==$_POST["password2"])
		{
			$checker->confirm_upload($_POST["password"]);
		}
		else
		{
			dr_return(105);
		}
	}
	else
	{
		echo("非法操作");
	}
	if(isset($default_service))
	{
		$default_service->show_default_links();
	}
}

function give_a_confirm_form($confirm_processor)
{
	global $color1,$color2;
	$color_switch=false;
	if(func_num_args()==2)
	{
		$confirm_memo=func_get_arg(1);
		$safe=true;
	}
	elseif(func_num_args()==3)
	{
		$default_service=func_get_arg(2);
		$confirm_memo=func_get_arg(1);
		$safe=true;
	}
	else
	{
		$confirm_memo="Unknown Action";
		$safe=false;
	}
	$checker=get_current_user_obj();
	
	global $dps_link;
	global $developer;
	
	if($dps_link!=FALSE)
	{
		$select_format='SELECT * FROM confirm WHERE epsn="%s" AND user_ID=%d';
		$query=sprintf($select_format,$checker->epsn,$checker->user_ID);
		if($developer)
			echo("give_a_confirm_form:".$query."<br />");
		$res_exist=mysql_query($query,$dps_link);
		if($obj_exist=mysql_fetch_object($res_exist))
			$exist=true;
		else
			$exist=false;
		//mysql_close($dps_link);
	}
	if(!$exist)
	{
		echo('<form method="POST" action="'.$confirm_processor.'">');
		echo("请您确认操作:".$confirm_memo."<br />");
		if(!$safe)
		{
			echo('<table border="2" align="left" cellspacing="2" cellpadding="2" width="100%" bgcolor="#ff8718">');
			echo('<caption>所有操作的清单</caption>');
			echo('<tr>');
			echo('<th scope="col">操作描述</th>');
			echo('<th scope="col">选择</th>');
			echo('</tr>');
			
			
			global $dps_link;
			global $developer;
			
			if($dps_link!=FALSE)
			{
				$select_format='SELECT * FROM upload_cache WHERE epsn=%d AND user_ID=%d';
				$query=sprintf($select_format,$checker->epsn,$checker->user_ID);
				if($developer)
				echo($query."<br />");
				$res_tocheck=mysql_query($query,$dps_link);
				while($obj_tocheck=mysql_fetch_object($res_tocheck))
				{
					switch($obj_tocheck->upload_type)
					{
						case 1:
							$str='增加一条"'.$obj_tocheck->var_ID.'"类型记录,其标题是“'.$obj_tocheck->caption.'”,内容是:“'.$obj_tocheck->memo.'"';
							break;
						case 2:
							$str='删除一条"'.$obj_tocheck->var_ID.'"类型记录,其标题是“'.$obj_tocheck->caption.'(如果标题为空，则所有该类型的变量都会被删除)';
							break;
						case 3:
							$str='重设"'.$obj_tocheck->var_ID.'"类型记录,将其标题改为“'.$obj_tocheck->caption.'”,内容改为:“'.$obj_tocheck->memo.'"(若留空表示不更改)';
							break;
						default:
							$str='不明操作（你怎么搞出来的？！）';
					}
					echo('<tr>');
					if($color_switch)
					{
						$color=$color1;
						$color_switch=false;
					}
					else
					{
						$color=$color2;
						$color_switch=true;
					}
					echo('<td bgcolor='.$color.'>'.$str.'</td>');
					echo('<td><input type="checkbox" name="ul_todel[]" value="'.$obj_tocheck->ul_ID.'"></td>');
					echo('</tr>');
				}
				//mysql_close($dps_link);
			}
			echo('</table>');
		}
		echo('如果您对此操作没有疑议，请输入您的密码两次后按“提交这些更新”按钮<br />');
		echo('请输入您的密码<input type="password" name="password" size=8><br />');
		echo('请再次您的密码<input type="password" name="password2" size=8><br />');
		echo('<input type="submit" name="submit" value="提交全部更新"><br />');
		if(!$safe)
			echo('<input type="submit" name="submit" value="删除这些更新"><br />');
		echo('</form>');
	}
	else
		if(isset($default_service))
		{
			$default_service->show_default_links();
		}
		echo('操作成功!<br />');
}

/******************************************************************************
  * Merge 3 arrays as a not_show list a join list and a base list(is exist).
  *
  * Returns true on success, false on error.
  *
  * usage: smart_merge(array $not_show,array $join[,array $base])
  *
  * @param     array $not_show			an array containing deleted or before reseted data
  * @param     array $join				an array containing added or after reseted data
  * @param     array $base				an array containing not edited data(optional)
  * @access    public
  * @return    boolean
  * @see       smart_get
  */
function smart_merge($not_show,$join)
{
	if(func_num_args()==3)
	{
		$base=func_get_arg(2);
		$m=count($base);
	}
	else
	{
		$m=0;
	}
	foreach($join as $join_single)
	{
		$not_deleted=true;
		foreach($not_show as $not_show_single)
		{
			if($not_show_single["caption"]==$join_single["caption"] AND ($not_show_single["memo"]==$join_single["memo"] OR $not_show_single["memo"]==""))
				$not_deleted=false;
		}
		if($not_deleted)
		{
			$base[$m]["caption"]=$join_single["caption"];
			$base[$m]["memo"]=$join_single["memo"];
			$m++;
		}
	}
	if($m=0)
		return null;
	else
		return $base;
}

/******************************************************************************
  * Calculate and output the date with the condition.It can calculate the date
  * before or after a certain date and output in DSTF(DistRema Standard Time Format)
  * for example, if you call this function with formated_date(2008,8,19,4) means 4 days
  * after 2008-8-19, the function will give you 2008-8-23 as return.
  *
  * Returns a DSTF on success, false on error.
  *
  * usage: formated_date(integer $y,integer $m,integer $d,integer $forward)
  *
  * @param		integer $y					year
  * @param		integer $m					month
  * @param		integer $d					day
  * @param		integer $forward				day(s) after the certain day,it can be either positive or nagetive
  * @access		public
  * @return		string
  */
function formated_date($y,$m,$d,$forward)
{
	if($m>12 OR $m<1)
	{
		return false;
	}
	$days[1]=31;
	if($y%4==0 AND ($y%100!=0 OR $y%400==0))
	{
		$days[2]=29;
		$year_days=366;
	}
	else
	{
		$days[2]=28;
		$year_days=365;
	}
	$days[3]=31;
	$days[4]=30;
	$days[5]=31;
	$days[6]=30;
	$days[7]=31;
	$days[8]=31;
	$days[9]=30;
	$days[10]=31;
	$days[11]=30;
	$days[12]=31;
	if(($y-1)%4==0 AND (($y-1)%100!=0 OR ($y-1)%400==0))
	{
		$pre_days[2]=29;
		$pre_year_days=366;
	}
	else
	{
		$pre_days[2]=28;
		$pre_year_days=365;
	}
	//Convert the date input into the days of the year
	$sum_date=0;
	for($i=1;$i<$m;$i++)
	{
		$sum_days=$sum_days+$days[$i];
	}
	$sum_days=$sum_days+$d+$forward;
	if($sum_days>$year_days)
	{
		$y++;
		$sum_days=$sum_days-$year_days;
	}
	while($sum_days<1)
	{
		$y--;
		if($y%4==0 AND ($y%100!=0 OR $y%400==0))
		{
			$days[2]=29;
			$year_days=366;
		}
		else
		{
			$days[2]=28;
			$year_days=365;
		}
		$sum_days=$sum_days+$year_days;
	}
	for($i=1;$sum_days>$days[$i];$i++)
	{
		$sum_days=$sum_days-$days[$i];
	}
	if($i<10)
		$m="0".$i;
	else
		$m=$i;
	if($sum_days<10)
		$d="0".$sum_days;
	else
		$d=$sum_days;
	return $y."-".$m."-".$d;
}

/******************************************************************************
  * Get data from search buffer
  *
  * Returns result in an array on success, false on error, NULL on not found.
  *
  * usage: get_searched_data(integer $var_ID,string $caption)
  *
  * @access		public
  * @param		integer $var_ID		the target variable type
  * @param		string $caption		the condition for the search
  * @return		array
  */
function get_searched_data($var_ID,$caption)
{
	global $dps_link;
	if($dps_link!=FALSE)
	{
		$select_format='SELECT caption,memo FROM search_buffer WHERE var_ID=%d AND caption LIKE "%s"';
		$query=sprintf($select_format,$var_ID,$caption."%");
		if($developer)
			echo("".$query."<br />");
		$res_searched=mysql_query($query,$dps_link);
		$m=0;
		while($obj_searched=mysql_fetch_object($res_searched))
		{
			$return_array[$m]["caption"]=$obj_searched->caption;
			$return_array[$m]["memo"]=$obj_searched->memo;
			$m++;
		}
		if($m==0)
			return NULL;
		else
			return $return_array;	
	}
	else
		return false;
}

/**
 * The user class offers the basic actions of a user. It's mainly about getting
 * data from the ccr directly. If you want to get data more smartly on a DPS, you
 * can use the child class-dps_user
 *
 * @version		0.5.35
 * @author		Arthur<arthur@cacomand.com>
 * @package		DPS
 *
 */
class dps_user extends user
{
	/******************************************************************************
	  * Increase the activity of a certain variable in the table "preload list"
	  *
	  * Returns true on success, false on error.
	  *
	  * usage: heat_var(integer $var_ID)
	  *
	  * @param		integer $var_ID				var type to increase activity
	  * @access		public
	  * @return		boolean
	  * @see		smart_get
	  */
	function heat_var($var_ID)
	{
		
		global $dps_link;
		global $developer;
		global $min_activity;
		
		if($dps_link!=FALSE)
		{
			$select_format='SELECT activity FROM preload_list WHERE epsn="%s" AND user_ID=%d AND var_ID=%d';
			$query=sprintf($select_format,$this->epsn,$this->user_ID,$var_ID);
			if($developer)
				echo("heat_var:".$query."<br />");
			$res_toheat=mysql_query($query,$dps_link);
			if($obj_toheat=mysql_fetch_object($res_toheat))
			{
				$update_format='UPDATE preload_list SET activity=%d WHERE epsn="%s" AND user_ID=%d AND var_ID=%d';
				$new_activity=$obj_toheat->activity+1;
				$query=sprintf($update_format,$new_activity,$this->epsn,$this->user_ID,$var_ID);
				if($developer)
					echo("heat_var:".$query."<br />");
				$res_nouse=mysql_query($query,$dps_link);
				if($new_activity>$min_activity AND $developer)
					echo("heat_var:variable ".$var_ID." from ".$this->epsn."->".$this->username."'s activity has reached the min activity<br />");				
			}
			else
			{
				$insert_format='INSERT INTO preload_list (epsn,user_ID,var_ID,activity) VALUE ("%s",%d,%d,1)';
				$query=sprintf($insert_format,$this->epsn,$this->user_ID,$var_ID);
				if($developer)
					echo("heat_var:".$query."<br />");
				$res_nouse=mysql_query($query,$dps_link);
				
			}
			if($developer)
				echo("heat_var:var type".$var_ID." of ".$this->epsn."->".$this->user_ID."has been heated.<br />");
			return true;
			//mysql_close($dps_link);
		}
		return false;
	}
	
	/******************************************************************************
	  * Add a veriable to the upload cache of the DPS.
	  *
	  * Returns true on success, false on error.
	  *
	  * usage: add_record($var_ID,$caption,$memo)
	  *
	  * @param		integer $var_ID				var type of the added record
	  * @param		string $caption				caption of the added record
	  * @param		string $memo				memo of the added record
	  * @access		public
	  * @return		boolean
	  */
	function add_record($var_ID,$caption,$memo)
	{
		
		global $dps_link;
		global $developer;
		
		if($dps_link!=FALSE)
		{
			$insert_format='INSERT INTO upload_cache (epsn,user_ID,var_ID,caption,memo,upload_type) VALUE ("%s",%d,%d,"%s","%s",1)';
			$query=sprintf($insert_format,$this->epsn,$this->user_ID,$var_ID,$caption,$memo);
			if($developer)
				echo("添加上传记录到缓存区:".$query."<br />");
			$res_nouse=mysql_query($query,$dps_link);
			//mysql_close($dps_link);
			return true;
		}
		return false;
	}
	
	/******************************************************************************
	  * reset a veriable to the upload cache of the DPS.
	  *
	  * Returns true on success, false on error.
	  *
	  * usage: reset_record(integer $var_ID[,string $caption[,string $memo]])
	  *
	  * @param		integer $var_ID				var type of the record to reset
	  * @param		string $caption				caption of the reseted record as condition.If left empty,all the record of this type will be merged into a record with the default caption and the new memo
	  * @param		string $memo				memo of the reseted record as new content
	  * @access		public
	  * @return		boolean
	  */
	function reset_record($var_ID)
	{
		
		global $dps_link;
		global $developer;
		//get the possible
		if(func_num_args()>1)
		$caption=func_get_arg(1);
		else
		$caption="";
		if(func_num_args()>2)
		$memo=func_get_arg(2);
		else
		$memo="";
		//if(func_num_args>3)
		//$file=func_get_arg(3);
		
		if($dps_link!=FALSE)
		{
			$select_format='SELECT FROM upload_cache WHERE epsn="%s" AND user_ID=%d AND var_ID=%d AND caption="%s" AND memo="%s" AND upload_type=3';
			$query=sprintf($select_format,$this->epsn,$this->user_ID,$var_ID,$caption,$memo);
			if($developer)
				echo("reset_record:".$query."<br />");
			$res_nouse=mysql_query($query,$dps_link);
			if($res_nouse!=false)//Search to check whether the new content is same with the new one
				return true;
			if(empty($caption) and empty($memo))
			{
				$delete_format='DELETE FROM upload_cache WHERE epsn="%s" AND user_ID=%d AND var_ID=%d AND upload_type=1';
				$query=sprintf($delete_format,$this->epsn,$this->user_ID,$var_ID);
				if($developer)
					echo("reset_record:".$query."<br />");
				$res_nouse=mysql_query($query,$dps_link);//delete the upload record of "ADD A VAR OF THIS VAR_ID"
				
				$delete_format='DELETE FROM upload_cache WHERE epsn="%s" AND user_ID=%d AND var_ID=%d AND upload_type=2';
				$query=sprintf($delete_format,$this->epsn,$this->user_ID,$var_ID);
				if($developer)
					echo("reset_record:".$query."<br />");
				$res_nouse=mysql_query($query,$dps_link);//delete the upload record of "DELETE VARS OF THIS VAR_ID"
			}
			elseif(!empty($caption) and empty($memo))
			{
				$delete_format='DELETE FROM upload_cache WHERE epsn="%s" AND user_ID=%d AND var_ID=%d AND caption="%s" AND upload_type=1';
				$query=sprintf($delete_format,$this->epsn,$this->user_ID,$var_ID,$caption);
				if($developer)
					echo("reset_record:".$query."<br />");
				$res_nouse=mysql_query($query,$dps_link);//delete the upload record of "ADD A VAR OF THIS VAR_ID"
				$delete_format='DELETE FROM upload_cache WHERE epsn="%s" AND user_ID=%d AND var_ID=%d AND caption="%s" AND upload_type=2';
				$query=sprintf($delete_format,$this->epsn,$this->user_ID,$var_ID,$caption);
				if($developer)
					echo("reset_record:".$query."<br />");
				$res_nouse=mysql_query($query,$dps_link);//delete the upload record of "DELETE VARS OF THIS VAR_ID"
			}
			elseif(!empty($caption) and !empty($memo))
			{
				$delete_format='DELETE FROM upload_cache WHERE epsn="%s" AND user_ID=%d AND var_ID=%d AND caption="%s" AND memo="%s" AND upload_type=1';
				$query=sprintf($delete_format,$this->epsn,$this->user_ID,$var_ID,$caption,$memo);
				if($developer)
					echo("reset_record:".$query."<br />");
				$res_nouse=mysql_query($query,$dps_link);//delete the upload record of "ADD A VAR OF THIS VAR_ID"
				$delete_format='DELETE FROM upload_cache WHERE epsn="%s" AND user_ID=%d AND var_ID=%d AND caption="%s" AND memo="%s" AND upload_type=2';
				$query=sprintf($delete_format,$this->epsn,$this->user_ID,$var_ID,$caption,$memo);
				if($developer)
					echo("reset_record:".$query."<br />");
				$res_nouse=mysql_query($query,$dps_link);//delete the upload record of "DELETE VARS OF THIS VAR_ID"
			}	
			
			$insert_format='INSERT INTO upload_cache (epsn,user_ID,var_ID,caption,memo,upload_type) VALUE ("%s",%d,%d,"%s","%s",3)';
			$query=sprintf($insert_format,$this->epsn,$this->user_ID,$var_ID,$caption,$memo);
			if($developer)
				echo("reset_record:".$query."<br />");
			$res_nouse=mysql_query($query,$dps_link);
			//mysql_close($dps_link);
			return true;
		}
		return false;
	}
	
	/******************************************************************************
	  * delete a veriable from the upload cache of the DPS.
	  *
	  * Returns true on success, false on error.
	  *
	  * usage: del_record(integer $var_ID[,string $caption[,string $memo]])
	  *
	  * @param		integer $var_ID				var type of the variable to delete
	  * @param		string $caption				caption as condition
	  * @param		string $memo				memo as condition
	  * @access		public
	  * @return		boolean
	  */
	function del_record($var_ID)
	{
		global $dps_link;
		global $developer;
		if($dps_link!=FALSE)
		{
			//get the caption if exist
			if(func_num_args()==1)
			{
				$caption="";
				$memo="";
			}
			elseif(func_num_args()==2)
			{
				$caption=func_get_arg(1);
				$memo="";
			}
			elseif(func_num_args()==3)
			{
				$caption=func_get_arg(1);
				$memo=func_get_arg(2);
			}
			else
				return false;
			//write the change into the upload_cache
			$select_format='SELECT FROM upload_cache WHERE epsn="%s" AND user_ID=%d AND var_ID=%d AND caption="%s" AND memo="%s" AND upload_type=2';
			$query=sprintf($select_format,$this->epsn,$this->user_ID,$var_ID,$caption,$memo);
			if($developer)
				echo("del_record:".$query."<br />");
			$res_nouse=mysql_query($query,$dps_link);//Search to check if exist a record which is totally the same
			if($res_nouse!=false)
				return true;
			
			if(empty($caption) and empty($memo))
			{
				$delete_format='DELETE FROM upload_cache WHERE epsn="%s" AND user_ID=%d AND var_ID=%d AND upload_type=1';
				$query=sprintf($delete_format,$this->epsn,$this->user_ID,$var_ID);
				if($developer)
					echo("del_record:".$query."<br />");
				$res_nouse=mysql_query($query,$dps_link);//delete the upload record of "ADD A VAR OF THIS VAR_ID"
				
				$delete_format='DELETE FROM upload_cache WHERE epsn="%s" AND user_ID=%d AND var_ID=%d AND upload_type=3';
				$query=sprintf($delete_format,$this->epsn,$this->user_ID,$var_ID);
				if($developer)
					echo("del_record:".$query."<br />");
				$res_nouse=mysql_query($query,$dps_link);//delete the upload record of "RESET VARS OF THIS VAR_ID"
			}
			elseif(!empty($caption) and empty($memo))
			{
				$delete_format='DELETE FROM upload_cache WHERE epsn="%s" AND user_ID=%d AND var_ID=%d AND caption="%s" AND upload_type=1';
				$query=sprintf($delete_format,$this->epsn,$this->user_ID,$var_ID,$caption);
				if($developer)
					echo("del_record:".$query."<br />");
				$res_nouse=mysql_query($query,$dps_link);//delete the upload record of "ADD A VAR OF THIS VAR_ID"
				$delete_format='DELETE FROM upload_cache WHERE epsn="%s" AND user_ID=%d AND var_ID=%d AND caption="%s" AND upload_type=3';
				$query=sprintf($delete_format,$this->epsn,$this->user_ID,$var_ID,$caption);
				if($developer)
					echo("del_record:".$query."<br />");
				$res_nouse=mysql_query($query,$dps_link);//delete the upload record of "RESET VARS OF THIS VAR_ID"
			}
			elseif(!empty($caption) and !empty($memo))
			{
				$delete_format='DELETE FROM upload_cache WHERE epsn="%s" AND user_ID=%d AND var_ID=%d AND caption="%s" AND memo="%s" AND upload_type=1';
				$query=sprintf($delete_format,$this->epsn,$this->user_ID,$var_ID,$caption,$memo);
				if($developer)
					echo("del_record:".$query."<br />");
				$res_nouse=mysql_query($query,$dps_link);//delete the upload record of "ADD A VAR OF THIS VAR_ID"
				$delete_format='DELETE FROM upload_cache WHERE epsn="%s" AND user_ID=%d AND var_ID=%d AND caption="%s" AND memo="%s" AND upload_type=3';
				$query=sprintf($delete_format,$this->epsn,$this->user_ID,$var_ID,$caption,$memo);
				if($developer)
					echo("del_record:".$query."<br />");
				$res_nouse=mysql_query($query,$dps_link);//delete the upload record of "RESET VARS OF THIS VAR_ID"
			}
			
			$insert_format='INSERT INTO upload_cache (epsn,user_ID,var_ID,caption,memo,upload_type) VALUE ("%s",%d,%d,"%s","%s",2)';
			$query=sprintf($insert_format,$this->epsn,$this->user_ID,$var_ID,$caption,$memo);
			if($developer)
				echo("del_record:".$query."<br />");
			$res_nouse=mysql_query($query,$dps_link);
			return true;
		}
	}
	
	/******************************************************************************
	  * Permit the DPS to give sync the user's data by telling it its password. The password
	  * in the database would be md5 encryped
	  *
	  * Returns true on success, false on error.
	  *
	  * usage: confirm_upload(string $password)
	  *
	  * @param		string password			user's password
	  * @access		public
	  * @return		boolean
	  * @see		user_upload
	  */
	function confirm_upload($password)
	{
		
		global $dps_link;
		global $developer;
		if(!isset($password) or $password=="")
			return false;
		
		if($dps_link!=FALSE)
		{
			$select_format='SELECT password FROM confirm WHERE epsn="%s" AND user_ID=%d';
			$query=sprintf($select_format,$this->epsn,$this->user_ID);
			if($developer)
				echo("认证上传".$query."<br />");
			$res_password=mysql_query($query,$dps_link);
			$exist_confirm=false;
			$same_password=false;
			if($obj_password=mysql_fetch_object($res_password))
			{
				$exist_confirm=true;
				if($developer)
					echo("认证上传:上传记录已存在<br />");
				if($obj_password->password==md5($password))
					$same_password=true;
			}
			if($exist_confirm==false OR $same_password==false)
			{
				$insert_format='INSERT INTO confirm (epsn,user_ID,password) VALUE ("%s",%d,"%s")';
				$query=sprintf($insert_format,$this->epsn,$this->user_ID,md5($password));
				if($developer)
					echo("认证上传".$query."<br />");
				$res_nouse=mysql_query($query,$dps_link);
				return true;
				//mysql_close($dps_link);
			}
		}
	}
	
	/******************************************************************************
	  * Get the value of this var type from the upload cache.
	  *
	  * Returns an array of data on success, false on error.
	  *
	  * usage: get_var_from_upload_cache($var_ID[,string caption])
	  *
	  * @param		integer $var_ID				var type of the var to get
	  * @param		string $caption				caption as search condition
	  * @access		public
	  * @return		array
	  * @see		smart_get
	  * @see		get_var_from_dps
 	  * @see		get_var_from_ccr
	  * @see		get_var_from_sent_data
	  */
	function get_var_from_upload_cache($var_ID)
	{
		
		global $dps_link;
		global $developer;
		if(func_num_args()>1)
			$caption=func_get_arg(1);
		else
			$caption="";
		
		if($dps_link!=FALSE)
		{
			if(empty($caption))
			{
				$select_format='SELECT caption,memo FROM upload_cache WHERE epsn="%s" AND user_ID=%d AND var_ID=%d AND caption="" AND upload_type=2';
				$query=sprintf($select_format,$this->epsn,$this->user_ID,$var_ID);
				$res_deleted=mysql_query($query,$dps_link);
				if($obj_deleted=mysql_fetch_object($res_deleted))
					return "null";//如果有一个全删的记录,直接就返回空就行了
				$select_format='SELECT caption,memo FROM upload_cache WHERE epsn="%s" AND user_ID=%d AND var_ID=%d AND upload_type=2';
				$query=sprintf($select_format,$this->epsn,$this->user_ID,$var_ID);
				$res_deleted=mysql_query($query,$dps_link);
				while($obj_deleted=mysql_fetch_object($res_deleted))
				{
					$not_show[]=$obj_deleted->caption;
				}
				$select_format='SELECT caption,memo FROM upload_cache WHERE epsn="%s" AND user_ID=%d AND var_ID=%d AND upload_type=3';
				$query=sprintf($select_format,$this->epsn,$this->user_ID,$var_ID);
				$res_reseted=mysql_query($query,$dps_link);
				$m=0;
				if($obj_reseted=mysql_fetch_object($res_reseted))
				{
					$return_array[$m]["caption"]=$obj_reseted->caption;
					$return_array[$m]["memo"]=$obj_reseted->memo;
					$m++;
					$select_format='SELECT caption,memo FROM upload_cache WHERE epsn="%s" AND user_ID=%d AND var_ID=%d AND caption!="%s" AND upload_type=1';
					$query=sprintf($select_format,$this->epsn,$this->user_ID,$var_ID,$obj_reseted->caption);
					if($developer)
						echo("get from upload cache:".$query."<br />");
					$res_added=mysql_query($query,$dps_link);
					while($obj_added=mysql_fetch_object($res_added))
					{
						$return_array[$m]["caption"]=$obj_added->caption;
						$return_array[$m]["memo"]=$obj_added->memo;
						$m++;
					}
					return $return_array;
				}
				else
				{
					$select_format='SELECT caption,memo FROM upload_cache WHERE epsn="%s" AND user_ID=%d AND var_ID=%d AND upload_type=1';
					$query=sprintf($select_format,$this->epsn,$this->user_ID,$var_ID);
					$res_added=mysql_query($query,$dps_link);
					if(mysql_num_rows($res_added)==0)
						return false;
					else
					{
						$m=0;
						while($obj_added=mysql_fetch_object($res_added))
						{
							$return_array[$m]["caption"]=$obj_added->caption;
							$return_array[$m]["memo"]=$obj_added->memo;
							$m++;
						}
						return $return_array;
					}
				}
			}
			else
			{
				$select_format='SELECT caption,memo FROM upload_cache WHERE epsn="%s" AND user_ID=%d AND var_ID=%d AND caption LIKE "%s" AND upload_type=2';
				$query=sprintf($select_format,$this->epsn,$this->user_ID,$var_ID,$caption."%");
				$res_deleted=mysql_query($query,$dps_link);
				if($obj_deleted=mysql_fetch_object($res_deleted))
					return false;
				else
				{
					$select_format='SELECT caption,memo FROM upload_cache WHERE epsn="%s" AND user_ID=%d AND var_ID=%d AND caption LIKE "%s" AND upload_type=3';
					$query=sprintf($select_format,$this->epsn,$this->user_ID,$var_ID,$caption."%");
					$res_reseted=mysql_query($query,$dps_link);
					if($obj_reseted=mysql_fetch_object($res_reseted))
					{
						$return_array[0]["caption"]=$obj_reseted->caption;
						$return_array[0]["memo"]=$obj_reseted->memo;
						return $return_array;
					}
					else
					{
						$select_format='SELECT caption,memo FROM upload_cache WHERE epsn="%s" AND user_ID=%d AND var_ID=%d AND caption LIKE "%s" AND upload_type=1';
						$query=sprintf($select_format,$this->epsn,$this->user_ID,$var_ID,$caption."%");
						$res_added=mysql_query($query,$dps_link);
						if(mysql_num_rows($res_added)==0)
							return false;
						else
						{
							$m=0;
							while($obj_added=mysql_fetch_object($res_added))
							{
								$return_array[$m]["caption"]=$obj_added->caption;
								$return_array[$m]["memo"]=$obj_added->memo;
								$m++;
							}
							return $return_array;
						}
					}
				}
			}
		}
		return false;	
	}
	
	/******************************************************************************
	  * Get the value of this var type from the download cache.
	  *
	  * Returns an array of data on success, false on error.
	  *
	  * usage: get_var_from_dps($var_ID[,string caption])
	  *
	  * @param		integer $var_ID				var type of the var to get
	  * @param		string $caption				caption as search condition
	  * @access		public
	  * @return		array
	  * @see		smart_get
	  * @see		get_var_from_upload_cache
	  * @see		get_var_from_ccr
	  * @see		get_var_from_sent_data
	  */
	function get_var_from_dps($var_ID)
	{
		//global $dps_host,$dps_username,$dps_password,$dps_basename;
		global $dps_link;
		global $developer;
		if(func_num_args()>1)
		$caption=func_get_arg(1);
		else
		$caption="";
		
		if($dps_link!=FALSE)
		{
			if(empty($caption))
			{
				$select_format='SELECT caption,memo FROM download_cache WHERE epsn="%s" AND user_ID=%d AND var_ID=%d';
				$query=sprintf($select_format,$this->epsn,$this->user_ID,$var_ID);
			}
			else
			{
				$select_format='SELECT caption,memo FROM download_cache WHERE epsn="%s" AND user_ID=%d AND var_ID=%d AND caption LIKE "%s"';
				$query=sprintf($select_format,$this->epsn,$this->user_ID,$var_ID,$caption."%");
			}
			if($developer)
				echo("get_var_from_dps:".$query."<br />");
			$res_var=mysql_query($query,$dps_link);
			//mysql_close($dps_link);//close the link here,for the function may escape during the return
			$m=0;
			while($obj_var=mysql_fetch_object($res_var))
			{
				$return_array[$m]["caption"]=$obj_var->caption;
				$return_array[$m]["memo"]=$obj_var->memo;
				$m++;
			}
			if($m!=0)
			{
				if($developer)
					echo("get_var_from_dps:Variable got os user ".$this->username." from DPS<br />");
				return $return_array;
			}
			else
			{
				if($developer)
					echo("get_var_from_dps:user ".$this->username."'s data not exist at DPS.<br />");
				return false;
			}
		}
		else
			return false;
	}
	
	/******************************************************************************
	  * Add a new var to the user's database with the default memo.
	  *
	  * Returns array of the default data on success, false on error.
	  *
	  * usage: register_new_var(integer $var_ID[,string caption])
	  *
	  * @param		integer $var_ID				var type of the variable to register
	  * @param		string $caption				define the caption user want(optional)
	  * @access		public
	  * @return		boolean
	  */
	function register_new_var($var_ID)
	{
		if(func_num_args()>1)
		$caption=func_get_arg(1);
		else
		$caption=get_default_caption($var_ID);
		$memo=get_default_memo($var_ID);
		$this->add_record($var_ID,$caption,$memo);
		$return_array[0]["caption"]=$caption;
		$return_array[0]["memo"]=$memo;
			echo("注册新变量:user: ".$this->username."'s data (var ID=".$var_ID.", caption=".$caption.") is registered,please confirm an update to apply it<br />");
		return $return_array;
	}
	
	/******************************************************************************
	  * Get the value of this var type from fastest database and merge it with the changes.
	  *
	  * Returns an array of data on success, false on error, null on not exist.
	  *
	  * usage: smart_get(boolean $reg,integer $var_ID[,string caption])
	  *
	  * @param		boolean @reg				whether to register a var or to return false if the variable is not exist
	  * @param		integer $var_ID				var type of the var to get
	  * @param		string $caption				caption as search condition
	  * @access		public
	  * @return		array
	  * @see		smart_get
	  * @see		get_var_from_upload_cache
	  * @see		get_var_from_ccr
	  * @see		get_var_from_sent_data
	  */
	function smart_get($reg,$var_ID)
	{
		
		global $dps_link;
		global $developer;
		if(func_num_args()==2)//if the caption is not defined
		{
			
			if($dps_link!=FALSE)
			{
				$select_format='SELECT caption,memo FROM upload_cache WHERE epsn="%s" AND user_ID=%d AND var_ID=%d AND caption is NULL AND upload_type=2';
				$query=sprintf($select_format,$this->epsn,$this->user_ID,$var_ID);
				$res_deleted=mysql_query($query,$dps_link);
				if($developer)
					echo("get from upload cache:".$query."<br />");
				if(mysql_num_rows($res_deleted)!=0)
					return null;//if there's a record deleting all this vars,return null directly
					
				$select_format='SELECT caption,memo FROM upload_cache WHERE epsn="%s" AND user_ID=%d AND var_ID=%d AND caption is NULL AND upload_type=3';
				$query=sprintf($select_format,$this->epsn,$this->user_ID,$var_ID);
				if($developer)
						echo("get from upload cache:".$query."<br />");
				$res_reseted=mysql_query($query,$dps_link);
				if($obj_reseted=mysql_fetch_object($res_reseted))
				{
					$return_array[0]["caption"]=get_default_caption($var_ID);
					$return_array[0]["memo"]=$obj_reseted->memo;
					return $return_array;//if there's a merge reset record, return the default caption and the memo directly
				}
				
				$select_format='SELECT caption,memo FROM upload_cache WHERE epsn="%s" AND user_ID=%d AND var_ID=%d AND upload_type=2';//add deleted record to the "not showing list"
				$query=sprintf($select_format,$this->epsn,$this->user_ID,$var_ID);
				$res_deleted=mysql_query($query,$dps_link);
				$n=0;
				$m=0;
				while($obj_deleted=mysql_fetch_object($res_deleted))
				{
					$not_show[$n]["caption"]=$obj_deleted->caption;
					$not_show[$n]["memo"]=$obj_deleted->memo;//memo is also a condition of delete
					$n++;
				}
				
				$select_format='SELECT caption,memo FROM upload_cache WHERE epsn="%s" AND user_ID=%d AND var_ID=%d AND upload_type=3';//add the reseted record to the "not showing list"
				$query=sprintf($select_format,$this->epsn,$this->user_ID,$var_ID);
				$res_reseted=mysql_query($query,$dps_link);
				while($obj_reseted=mysql_fetch_object($res_reseted))
				{
					$not_show[$n]["caption"]=$obj_reseted->caption;
					$not_show[$n]["memo"]="";//caption is the only condition for reset
					$n++;
					$base[$m]["caption"]=$obj_reseted->caption;
					$base[$m]["memo"]=$obj_reseted->memo;//add the record after reset to the "base list"
					if($developer)
						echo("reset record got from upload cache:".$obj_reseted->caption."/".$obj_reseted->memo."<be />");
					$m++;
				}
				
				$select_format='SELECT caption,memo FROM upload_cache WHERE epsn="%s" AND user_ID=%d AND var_ID=%d AND upload_type=1';//add the added record to the "base list"
				$query=sprintf($select_format,$this->epsn,$this->user_ID,$var_ID);
				if($developer)
						echo("get from upload cache:".$query."<br />");
				$res_added=mysql_query($query,$dps_link);
				while($obj_added=mysql_fetch_object($res_added))
				{
					if($obj_added->caption=="")
						$obj_added->caption=get_default_caption($var_ID);
					if($obj_added->memo=="")
						$obj_added->memo=get_default_memo($var_ID);
					$base[$m]["caption"]=$obj_added->caption;
					$base[$m]["memo"]=$obj_added->memo;
					if($developer)
						echo("add record got from upload cache:".$obj_added->caption."/".$obj_added->memo."<br />");
					$m++;
				}
			}
			else
				return false;
			if($return_array=$this->get_var_from_dps($var_ID))
				;
			elseif($return_array=$this->get_var_from_ccr($var_ID))
				$this->heat_var($var_ID);
			elseif($return_array=$this->get_var_from_sent_data($var_ID))
				;
			else
			{
				if(count($base)!=0)
					return $base;
				elseif($reg)
				{
					if($return_array[0]["caption"]=get_default_caption($var_ID) AND $return_array[0]["memo"]=get_default_memo($var_ID))
						return $return_array;
					else
						return false;
				}
				else
					return null;	
			}
			//if the program runs to here, it means the function has got data
			$final_show=@smart_merge($not_show,$return_array,$base);
			return $final_show;
		}
		else
		{
			$caption=func_get_arg(2);
			
			if($dps_link!=FALSE)
			{
				$select_format='SELECT caption,memo FROM upload_cache WHERE epsn="%s" AND user_ID=%d AND var_ID=%d AND caption="%s" AND memo is NULL AND upload_type=2';
				$query=sprintf($select_format,$this->epsn,$this->user_ID,$var_ID,$caption);
				$res_deleted=mysql_query($query,$dps_link);
				if($developer)
					echo("get from upload cache:".$query."<br />");
				if(mysql_num_rows($res_deleted)!=0)
					return null;//if there's a record deleting all this vars,return null directly
					
				$select_format='SELECT caption,memo FROM upload_cache WHERE epsn="%s" AND user_ID=%d AND var_ID=%d AND caption="%s" AND memo is NULL AND upload_type=3';
				$query=sprintf($select_format,$this->epsn,$this->user_ID,$var_ID,$caption);
				if($developer)
						echo("get from upload cache:".$query."<br />");
				$res_reseted=mysql_query($query,$dps_link);
				if($obj_reseted=mysql_fetch_object($res_reseted))
				{
					$return_array[0]["caption"]=$caption;
					$return_array[0]["memo"]=$obj_reseted->memo;
					return $return_array;//if there's a merge reset record, return the default caption and the memo directly
				}
				
				$select_format='SELECT caption,memo FROM upload_cache WHERE epsn="%s" AND user_ID=%d AND var_ID=%d AND caption="%s" AND upload_type=2';//add deleted record to the "not showing list"
				$query=sprintf($select_format,$this->epsn,$this->user_ID,$var_ID,$caption);
				$res_deleted=mysql_query($query,$dps_link);
				$n=0;
				$m=0;
				while($obj_deleted=mysql_fetch_object($res_deleted))
				{
					$not_show[$n]["caption"]=$obj_deleted->caption;
					$not_show[$n]["memo"]=$obj_deleted->memo;//memo is also a condition of delete
					$n++;
				}
				
				$select_format='SELECT caption,memo FROM upload_cache WHERE epsn="%s" AND user_ID=%d AND var_ID=%d AND caption="%s" AND upload_type=3';
				$query=sprintf($select_format,$this->epsn,$this->user_ID,$var_ID,$caption);
				$res_reseted=mysql_query($query,$dps_link);
				while($obj_reseted=mysql_fetch_object($res_reseted))
				{
					$not_show[$n]["caption"]=$obj_reseted->caption;
					$not_show[$n]["memo"]="";
					$n++;
					$base[$m]["caption"]=$obj_reseted->caption;
					$base[$m]["memo"]=$obj_reseted->memo;
					if($developer)
						echo("reset record got from upload cache:".$obj_reseted->caption."/".$obj_reseted->memo."<br />");
					$m++;
				}
				
				$select_format='SELECT caption,memo FROM upload_cache WHERE epsn="%s" AND user_ID=%d AND var_ID=%d AND caption="%s" AND upload_type=1';
				$query=sprintf($select_format,$this->epsn,$this->user_ID,$var_ID,$caption);
				if($developer)
						echo("get from upload cache:".$query."<br />");
				$res_added=mysql_query($query,$dps_link);
				while($obj_added=mysql_fetch_object($res_added))
				{
					if($obj_added->memo=="")
						$obj_added->memo=get_default_memo($var_ID);
					$base[$m]["caption"]=$obj_added->caption;
					$base[$m]["memo"]=$obj_added->memo;
					if($developer)
						echo("add record got from upload cache:".$obj_added->caption."/".$obj_added->memo."<br />");
					$m++;
				}
			}
			else
				return false;
			if($return_array=$this->get_var_from_dps($var_ID,$caption))
				;
			elseif($return_array=$this->get_var_from_ccr($var_ID,$caption))
				$this->heat_var($var_ID);
			elseif($return_array=$this->get_var_from_sent_data($var_ID,$caption))
				;
			else
			{
				if(count($base)!=0)
					return $base;
				elseif($reg)
				{
					if($return_array[0]["caption"]=$caption AND $return_array[0]["memo"]=get_default_memo($var_ID))
						return $return_array;
					else
						return false;
				}
				else
					return null;	
			}
			$final_show=@smart_merge($not_show,$return_array,$base);
			return $final_show;
		}
	}
}

/**
 * The dps_action class offers some of the user actions on the dps such as sync with CCR or search the CCRs
 *
 * @version		0.5.35
 * @author		Arthur<arthur@cacomand.com>
 * @package		DPS
 *
 */
class dps_action
{
	private $dps_power_username,$dps_power_password;
	/******************************************************************************
	  * Constructor of the class dps_action.Defines the full privilege username and password of the dps
	  *
	  * Returns true on success, false on error or fail.
	  *
	  * usage: dps_action(string $dps_power_username,string $dps_power_password)
	  *
	  * @param		string $username				username of full privilege user
	  * @param		string $password				password of full privilege user
	  * @access		public
	  * @return		boolean
	  */
	function dps_action($dps_power_username,$dps_power_password)
	{
		global $developer;
		if(isset($dps_power_username) AND isset($dps_power_password))
		{
			if($developer)
				echo("Object of DPS_ACTION created<br />");
			$this->dps_power_username=$dps_power_username;
			$this->dps_power_password=$dps_power_password;
			return true;
		}
		else
			return false;
	}
			
	/******************************************************************************
	  * Search all the CCRs around the world for a certain type of var.The result will be
	  * stored in the DPS.search_buffer
	  *
	  * Returns true on success, false on error or fail.
	  *
	  * usage: search_renew(string $var_ID)
	  *
	  * @param		integer $var_ID				var type to search 
	  * @access		public
	  * @return		boolean
	  */
	function search_renew($var_ID)
	{
		global $ref_link;
		global $developer;		
		global $dps_link;
		global $developer;
		global $ccr_public_username,$ccr_public_key,$ccr_basename;
		if ($ref_link!=FALSE)
		{
			if(!isset($varID))
				return false;
			
			if($dps_link!=FALSE)
			{
				$delete_format='DELETE FROM search_buffer WHERE var_ID=%d';
				$query=sprintf($delete_format,$var_ID);
				if($developer)
					echo("search_renew:".$query."<br />");
				$res_nouse=mysql_query($query,$dps_link);
			}
			
			$query='SELECT IP_address,epsn FROM epsn_pool';
			if($developer)
				echo("search_renew:".$query."<br />");
			$res_tosearch=mysql_query($query,$ref_link);
			while($obj_tosearch=mysql_fetch_object($res_tosearch))
			{
				//open an CCR link to search
				$ccr_link=mysql_connect($obj_tosearch->IP_address,$ccr_public_username,$ccr_public_key);//this link must be outside the class
				mysql_select_db($ccr_basename,$ccr_link);
				if($ccr_link!=FALSE)
				{
					$query='SELECT user_ID FROM user_list';
					if($developer)
						echo("search_renew:".$query."<br />");
					$res_user_IDs=mysql_query($query,$ccr_link);
					while($obj_user_IDs=mysql_fetch_object($res_user_IDs))//search for the data of a single user
					{
						$user_to_search=new dps_user($obj_tosearch->epsn,$obj_user_IDs->user_ID);
						if($res=$user_to_search->smart_get(false,$var_ID))
						{
							foreach($res as $record)
							{
								$insert_format='INSERT INTO search_buffer (var_ID,caption,memo,renew_time,epsn,user_ID) VALUE (%d,"%s","%s","%s","%s",%d)';
								$query=sprintf($insert_format,$var_ID,$record["caption"],$record["memo"],date("Y/m/d/G/i/s"),$user_to_search->epsn,$user_to_search->user_ID);
								if($developer)
									echo("search_renew:".$query."<br />");
								$res_nouse=mysql_query($query,$dps_link);
							}
						}
					}
				}
				else
					return false;
			}
			return true;
		}
		return false;
	}
	
	/******************************************************************************
	  * Clear the download buffer.
	  *
	  * Returns true on success, false on error or fail.
	  *
	  * usage: clear_download_buffer()
	  *
	  * @access		public
	  * @return		boolean
	  */
	function clear_download_buffer()
	{
		
		global $dps_link;
		global $developer;
		
		if($dps_link!=FALSE)
		{
			$query="TRUNCATE TABLE `download_cache`";
			if($developer)
				echo("TRUNCATE DOWNLOAD BUFFER:".$query."<br />");
			$res_nouse=mysql_query($query,$dps_link);
			return true;
		}
		return false;
	}
	
	/******************************************************************************
	  * Clear the upload buffer.
	  *
	  * Returns true on success, false on error or fail.
	  *
	  * usage: clear_upload_buffer()
	  *
	  * @access		public
	  * @return		boolean
	  */
	function clear_upload_buffer()
	{
		
		global $dps_link;
		global $developer;
		
		if($dps_link!=FALSE)
		{
			$query="TRUNCATE TABLE `upload_cache` ";
			if($developer)
				echo("TRUNCATE UPLOAD BUFFER:".$query."<br />");
			$res_nouse=mysql_query($query,$dps_link);
		}
	}
	
	/******************************************************************************
	  * Preload the variables whose activity has reached the $min_activity.
	  *
	  * Returns true on success, false on error or fail.
	  *
	  * usage: preload()
	  *
	  * @see		min_activity
	  * @access		public
	  * @return		boolean
	  */
	function preload()
	{
		
		global $dps_link;
		global $ccr_public_username,$ccr_public_key,$ccr_basename;
		global $developer;
		global $min_activity;
		$this->clear_download_buffer();
		
		if($dps_link!=FALSE)
		{
			$select_format='SELECT epsn,user_ID,var_ID FROM preload_list WHERE activity>%d';
			$query=sprintf($select_format,$min_activity);
			if($developer)
				echo("Preload:".$query."<br />");//to find out the IP address for this epsn
			$res_user=mysql_query($query,$dps_link);
			while($obj_user=mysql_fetch_object($res_user))
			{
				$ccr_link=mysql_connect(get_ccr_host($obj_user->epsn),$ccr_public_username,$ccr_public_key);//this link must be outside the class
				mysql_select_db($ccr_basename,$ccr_link);
				if($ccr_link!=False)
				{
					$select_format='SELECT caption,memo FROM variables_%d WHERE var_ID=%d';
					$query=sprintf($select_format,$obj_user->user_ID,$obj_user->var_ID);
					if($developer)
						echo("Preload".$query."<br />");
					$res_todownload=mysql_query($query,$ccr_link);
					while($obj_todownload=mysql_fetch_object($res_todownload))
					{
						$insert_format='INSERT INTO download_cache (epsn,user_ID,var_ID,caption,memo) VALUE ("%s",%d,%d,"%s","%s")';
						$query=sprintf($insert_format,$obj_user->epsn,$obj_user->user_ID,$obj_user->var_ID,$obj_todownload->caption,$obj_todownload->memo);
						if($developer)
							echo("Preload:".$query."<br />");
						$res_nouse=mysql_query($query,$dps_link);
						if($developer)
							echo("Preload:".$obj_user->epsn."->".$obj_todownload->user_ID." has a record preloaded.<br />");
					}
					//mysql_close($ccr_link);
				}
				else
				{
					$delete_format="DELETE FROM preload_list WHERE pl_ID=%d";
					$query=sprintf($delete_format,$obj_user->pl_ID);
					if($developer)
						echo("Preload:".$query."<br />");
					$res_nouse=mysql_query($query,$dps_link);
				}
			}
			$query='SELECT activity,epsn,user_ID,var_ID FROM preload_list';
			if($developer)
				echo("Preload:".$query."<br />");//to find out the IP address for this epsn
			$res_activity=mysql_query($query,$dps_link);
			while($obj_activity=mysql_fetch_object($res_activity))
			{
				$update_format='UPDATE preload_list SET activity=%d WHERE epsn="%s" user_ID=%d AND var_ID=%d';
				$query=sprintf($update_format,$obj_activity->activity-1,$obj_activity->epsn,$obj_activity->user_ID,$obj_activity->var_ID);
				if($developer)
					echo("Preload:".$query."<br />");
				$res_nouse=mysql_query($query,$dps_link);
			}
		}
	}
	
	/******************************************************************************
	  * Upload all the variables stored in the upload buffer and has a authorization
	  * in the DPS.confirm 
	  *
	  * Returns true on success, false on error or fail.
	  *
	  * usage: great_upload()
	  *
	  * @see		user_upload
	  * @access		public
	  * @return		boolean
	  */
	function great_upload()
	{
		
		global $dps_link;
		global $developer;
		if($dps_link!=FALSE)
		{
			$query='SELECT * FROM confirm';
			if($developer)
				echo("great_upload:".$query."<br />");//to find out the infomation for this username at ccr server
			$res_cfm=mysql_query($query,$dps_link);
			while($obj_cfm=mysql_fetch_object($res_cfm))
			{
				if($this->user_upload($obj_cfm->epsn,$obj_cfm->user_ID,$obj_cfm->password))
				{
					$delete_format="DELETE FROM confirm WHERE cfm_ID=%d";
					$query=sprintf($delete_format,$obj_cfm->cfm_ID);
					if($developer)
						echo("great_upload:".$query."<br />");
					$res_nouse=mysql_query($query,$dps_link);
				}
				else
				{
					echo("great_upload:".get_username($obj_cfm->epsn,$obj_cfm->user_ID)."'s password is wrong...authorization cancelled<br />");
					mysql_select_db($dps_basename,$dps_link);
					$delete_format="DELETE FROM confirm WHERE cfm_ID=%d";
					$query=sprintf($delete_format,$obj_cfm->cfm_ID);
					if($developer)
						echo("great_upload:".$query."<br />");
					$res_nouse=mysql_query($query,$dps_link);
					return false;
				}
			}
				echo("great_upload:Great upload done……<br />");
			return true;
		}
		return false;
	}
	
	/******************************************************************************
	  * Sync the DPS with the user's CCR.
	  *
	  * Returns true on success, false on error or fail.
	  *
	  * usage: user_upload(string $epsn,integer $user_ID,string $password)
	  *
	  * @param		string epsn			epsn of the uploading user
  	  * @param		integer user_ID		user_ID of the uploading user
   	  * @param		string password		password of the uploading user(md5 encrypted)
	  * @access		public
	  * @return		boolean
	  */
	function user_upload($epsn,$user_ID,$password)
	{
		
		global $dps_link;
		global $developer;
		global $ccr_basename,$ccr_public_username,$ccr_public_key;
				
		$ccr_link=mysql_connect(get_ccr_host($epsn),$ccr_public_username,$ccr_public_key);
		mysql_select_db($ccr_basename,$ccr_link);
		if($ccr_link!=FALSE)
		{
			$select_format='SELECT password FROM user_list WHERE user_ID=%d';
			$query=sprintf($select_format,$user_ID);
			if($developer)
				echo("user_upload:".$query."<br />");
			$res_password=mysql_query($query,$ccr_link);
			if($obj_password=mysql_fetch_object($res_password))
			{
				$right_password=$obj_password->password;
				if($developer)
					echo("user_upload:correct password got: ".$right_password."<br />compared with input:".$password."<br />");
			}
		}
		if($dps_link!=FALSE and $right_password==$password)
		{
			if($developer)
				echo("user_upload:Password checked");
			//deal with the deletes
			$select_format='SELECT * FROM upload_cache WHERE epsn="%s" AND user_ID=%d AND upload_type=2';
			$query=sprintf($select_format,$epsn,$user_ID);
			if($developer)
				echo("user_upload:".$query."<br />");
			$res_todel=mysql_query($query,$dps_link);
			while($obj_todel=mysql_fetch_object($res_todel))
			{
				//Deal with recoreds in the CCR.variables_x
				if(empty($obj_todel->caption))//caption is empty or both caption and memo are empty,means delete all the var type
				{
					$delete_format='DELETE FROM variables_%d WHERE var_ID=%d';
					$query=sprintf($delete_format,$obj_todel->user_ID,$obj_todel->var_ID);
				}
				elseif(empty($obj_todel->memo))//caption is not empty while memo is empty,means use caption alone as condition
				{
					$delete_format='DELETE FROM variables_%d WHERE var_ID=%d AND caption like "%s"';
					$query=sprintf($delete_format,$obj_todel->user_ID,$obj_todel->var_ID,$obj_todel->caption."%");
				}
				else//Both caption and memo are not empty means user both as condition
				{
					$delete_format='DELETE FROM variables_%d WHERE var_ID=%d AND caption LIKE "%s" AND memo LIKE "%s"';
					$query=sprintf($delete_format,$obj_todel->user_ID,$obj_todel->var_ID,$obj_todel->caption."%",$obj_todel->memo."%");
				}
				if($developer)
					echo("user_upload:".$query."<br />");
				$res_nouse=mysql_query($query,$ccr_link);
				//Deal with recoreds in the CCR.sent_data_pool
				if(empty($obj_todel->caption))//caption is empty or both caption and memo are empty,means delete all the var type
				{
					$delete_format='DELETE FROM sent_data_pool WHERE user_ID=%d AND var_ID=%d';
					$query=sprintf($delete_format,$obj_todel->user_ID,$obj_todel->var_ID);
				}
				elseif(empty($obj_todel->memo))//caption is not empty while memo is empty,means use caption alone as condition
				{
					$delete_format='DELETE FROM sent_data_pool WHERE user_ID=%d AND var_ID=%d AND caption like "%s"';
					$query=sprintf($delete_format,$obj_todel->user_ID,$obj_todel->var_ID,$obj_todel->caption."%");
				}
				else//Both caption and memo are not empty means user both as condition
				{
					$delete_format='DELETE FROM sent_data_pool WHERE user_ID=%d AND var_ID=%d AND caption LIKE "%s" AND memo LIKE "%s"';
					$query=sprintf($delete_format,$obj_todel->user_ID,$obj_todel->var_ID,$obj_todel->caption."%",$obj_todel->memo."%");
				}
				if($developer)
					echo("user_upload:".$query."<br />");
				$res_nouse=mysql_query($query,$ccr_link);
				//delete the upload command.
				$delete_format="DELETE FROM upload_cache WHERE ul_ID=%d";
				$query=sprintf($delete_format,$obj_todel->ul_ID);
				if($developer)
					echo("user_upload".$query."<br />");
				$res_nouse=mysql_query($query,$dps_link);
				
			}
			
			//deal with the adds
			$select_format='SELECT * FROM upload_cache WHERE epsn="%s" AND user_ID=%d AND upload_type=1';
			$query=sprintf($select_format,$epsn,$user_ID);
			if($developer)
				echo("user_upload:".$query."<br />");
			$res_toadd=mysql_query($query,$dps_link);
			while($obj_toadd=mysql_fetch_object($res_toadd))
			{
				if($obj_toadd->caption=="")
					$obj_toadd->caption=get_default_caption($obj_toadd->var_ID);
				if($obj_toadd->memo=="")
					$obj_toadd->memo=get_default_memo($obj_toadd->var_ID);
				$insert_format='INSERT INTO variables_%d (var_ID,caption,memo) VALUE (%d,"%s","%s")';
				$query=sprintf($insert_format,$obj_toadd->user_ID,$obj_toadd->var_ID,$obj_toadd->caption,$obj_toadd->memo);
				if($developer)
					echo("user_upload:".$query."<br />");
				$res_nouse=mysql_query($query,$ccr_link);
				
				$delete_format="DELETE FROM upload_cache WHERE ul_ID=%d";
				$query=sprintf($delete_format,$obj_toadd->ul_ID);
				if($developer)
					echo("user_upload:".$query."<br />");
				$res_nouse=mysql_query($query,$dps_link);
				
			}
			
			//deal with the resets
			$select_format='SELECT * FROM upload_cache WHERE epsn="%s" AND user_ID=%d AND upload_type=3';
			$query=sprintf($select_format,$epsn,$user_ID);
			if($developer)
				echo("user_upload".$query."<br />");
			$res_toreset=mysql_query($query,$dps_link);
			while($obj_toreset=mysql_fetch_object($res_toreset))
			{
				$select_format='SELECT rec_ID FROM variables_%d WHERE var_ID=%d AND caption="%s"';
				$query=sprintf($select_format,$obj_toreset->user_ID,$obj_toreset->var_ID,$obj_toreset->caption);
				if($developer)
					echo("user_upload".$query."<br />");
				$res_exist=mysql_query($query);
				if($obj_exist=mysql_fetch_object($res_exist))
				{
					if(empty($obj_toreset->caption))//edit the memo
					{
						$update_format='UPDATE variables_%d SET caption="%s",memo="%s" WHERE var_ID=%d';
						$query=sprintf($update_format,$obj_toreset->user_ID,get_default_caption($obj_toreset->var_ID),$obj_toreset->memo,$obj_toreset->var_ID);
						if($developer)
							echo("user_upload".$query."<br />");
						$res_nouse=mysql_query($query,$ccr_link);
					}
					else//edit memo and use caption as condition
					{
						$update_format='UPDATE variables_%d SET memo="%s" WHERE var_ID=%d AND caption="%s"';
						$query=sprintf($update_format,$obj_toreset->user_ID,$obj_toreset->memo,$obj_toreset->var_ID,$obj_toreset->caption);
						if($developer)
							echo("user_upload:".$query."<br />");
						$res_nouse=mysql_query($query,$ccr_link);
					}
				}
				else
				{
					$insert_format='INSERT INTO variables_%d (var_ID,caption,memo) VALUE (%d,"%s","%s")';
					$query=sprintf($insert_format,$obj_toreset->user_ID,$obj_toreset->var_ID,$obj_toreset->caption,$obj_toreset->memo);
					if($developer)
						echo("user_upload:".$query."<br />");
					$res_nouse=mysql_query($query,$ccr_link);
				}
				$delete_format="DELETE FROM upload_cache WHERE ul_ID=%d";
				$query=sprintf($delete_format,$obj_toreset->ul_ID);
				if($developer)
					echo("user_upload:".$query."<br />");
				$res_nouse=mysql_query($query,$dps_link);
				
			}
			//mysql_close($ccr_link);
			//mysql_close($dps_link);
			if($developer)
				echo("user_upload:user ".$username."'s data has been uploaded<br />");
			return true;
		}
		return false;
	}
}//end of class dps_action

class service
{
	public $service_name;
	function show_default_links()
	{}
}

/**
 * The smtp class is for the dps to send emails via exsiting mailboxs
 *
 * @version		0.5.35
 * @author		Unknown
 * @package		DPS
 *
 */

class smtp
{
	/* Public Variables */
	var $smtp_port;
	var $time_out;
	var $host_name;
	var $log_file;
	var $relay_host;
	var $debug;
	var $auth;
	var $user;
	var $pass;

	/* Private Variables */ 
	var $sock;

	/* Constractor */
	function smtp($relay_host = "", $smtp_port = 25,$auth = false,$user,$pass)
	{
		$this->debug = FALSE;
		$this->smtp_port = $smtp_port;
		$this->relay_host = $relay_host;
		$this->time_out = 30; //is used in fsockopen() 
		
		#
		$this->auth = $auth;//auth
		$this->user = $user;
		$this->pass = $pass;
		
		#
		$this->host_name = "localhost"; //is used in HELO command 
		$this->log_file = "";

		$this->sock = FALSE;
	}

	/* Main Function */
	function sendmail($to, $from, $subject = "", $body = "", $mailtype, $cc = "", $bcc = "", $additional_headers = "")
	{
		$mail_from = $this->get_address($this->strip_comment($from));
		$body = ereg_replace("(^|(\r\n))(\.)", "\1.\3", $body);
		$header = "MIME-Version:1.0\r\n";

		if($mailtype=="HTML")
		{
			$header .= "Content-Type:text/html\r\n charset=utf-8";
		}

		$header .= "To: ".$to."\r\n";

		if ($cc != "") 
		{
			$header .= "Cc: ".$cc."\r\n";
		}

		$header .= "From: $from<".$from.">\r\n";
		$header .= "Subject: ".$subject."\r\n";
		$header .= $additional_headers;
		$header .= "Date: ".date("r")."\r\n";
		$header .= "X-Mailer:By Redhat (PHP/".phpversion().")\r\n";

		list($msec, $sec) = explode(" ", microtime());

		$header .= "Message-ID: <".date("YmdHis", $sec).".".($msec*1000000).".".$mail_from.">\r\n";

		$TO = explode(",", $this->strip_comment($to));

		if ($cc != "") 
		{
			$TO = array_merge($TO, explode(",", $this->strip_comment($cc)));
		}

		if ($bcc != "") 
		{
			$TO = array_merge($TO, explode(",", $this->strip_comment($bcc)));
		}

		$sent = TRUE;

		foreach ($TO as $rcpt_to) 
		{
			$rcpt_to = $this->get_address($rcpt_to);
			
			if (!$this->smtp_sockopen($rcpt_to))
			{
				$this->log_write("Error: Cannot send email to ".$rcpt_to."\n");
				$sent = FALSE;
				continue;
			}

			if ($this->smtp_send($this->host_name, $mail_from, $rcpt_to, $header, $body)) 
			{
				$this->log_write("E-mail has been sent to <".$rcpt_to.">\n");
			} 
			else 
			{
				$this->log_write("Error: Cannot send email to <".$rcpt_to.">\n");
				$sent = FALSE;
			}

			fclose($this->sock);

			$this->log_write("Disconnected from remote host\n");
		}

		return $sent;
	}

	/* Private Functions */
	function smtp_send($helo, $from, $to, $header, $body = "")
	{
		if (!$this->smtp_putcmd("HELO", $helo)) 
		{

			return $this->smtp_error("sending HELO command");
		}

		#auth
		if($this->auth)
		{
			if (!$this->smtp_putcmd("AUTH LOGIN", base64_encode($this->user))) 
			{
				return $this->smtp_error("sending HELO command");
			}

			if (!$this->smtp_putcmd("", base64_encode($this->pass))) 
			{
				return $this->smtp_error("sending HELO command");
			}
		}

		#
		if (!$this->smtp_putcmd("MAIL", "FROM:<".$from.">")) 
		{
			return $this->smtp_error("sending MAIL FROM command");
		}

		if (!$this->smtp_putcmd("RCPT", "TO:<".$to.">"))
		{
			return $this->smtp_error("sending RCPT TO command");
		}

		if (!$this->smtp_putcmd("DATA"))
		{
			return $this->smtp_error("sending DATA command");
		}

		if (!$this->smtp_message($header, $body)) 
		{
			return $this->smtp_error("sending message");
		}

		if (!$this->smtp_eom()) 
		{
			return $this->smtp_error("sending <CR><LF>.<CR><LF> [EOM]");
		}

		if (!$this->smtp_putcmd("QUIT")) 
		{
			return $this->smtp_error("sending QUIT command");
		}

		return TRUE;
	}


	function smtp_sockopen($address)
	{
		if ($this->relay_host == "") 
		{
			return $this->smtp_sockopen_mx($address);
		} 
		else 
		{
			return $this->smtp_sockopen_relay();
		}
	}

	function smtp_sockopen_relay()
	{
		$this->log_write("Trying to ".$this->relay_host.":".$this->smtp_port."\n");
		$this->sock = @fsockopen($this->relay_host, $this->smtp_port, $errno, $errstr, $this->time_out);
		if (!($this->sock && $this->smtp_ok())) 
		{
			$this->log_write("Error: Cannot connenct to relay host ".$this->relay_host."\n");
			$this->log_write("Error: ".$errstr." (".$errno.")\n");
			return FALSE;
		}

		$this->log_write("Connected to relay host ".$this->relay_host."\n");
		return TRUE;
	}

	function smtp_sockopen_mx($address)
	{
		$MXHOSTS[0]="";
		$domain = ereg_replace("^.+@([^@]+)$", "\1", $address);
		if (!@getmxrr($domain, $MXHOSTS)) 
		{
			$this->log_write("Error: Cannot resolve MX \"".$domain."\"\n");
			return FALSE;
		}
		
		foreach ($MXHOSTS as $host) 
		{
			$this->log_write("Trying to ".$host.":".$this->smtp_port."\n");
			$this->sock = @fsockopen($host, $this->smtp_port, $errno, $errstr, $this->time_out);
			if (!($this->sock && $this->smtp_ok())) 
			{
				$this->log_write("Warning: Cannot connect to mx host ".$host."\n");
				$this->log_write("Error: ".$errstr." (".$errno.")\n");
				continue;
			}

			$this->log_write("Connected to mx host ".$host."\n");
			return TRUE;
		}

		$this->log_write("Error: Cannot connect to any mx hosts (".implode(", ", $MXHOSTS).")\n");
		return FALSE;
	}

	function smtp_message($header, $body)
	{
		fputs($this->sock, $header."\r\n".$body);
		$this->smtp_debug("> ".str_replace("\r\n", "\n"."> ", $header."\n> ".$body."\n> "));
		return TRUE;
	}

	function smtp_eom()
	{
		fputs($this->sock, "\r\n.\r\n");
		$this->smtp_debug(". [EOM]\n");
		return $this->smtp_ok();
	}

	function smtp_ok()
	{
		$response = str_replace("\r\n", "", fgets($this->sock, 512));
		$this->smtp_debug($response."\n");
	 
		if (!ereg("^[23]", $response)) 
		{
			fputs($this->sock, "QUIT\r\n");
			fgets($this->sock, 512);
			$this->log_write("Error: Remote host returned \"".$response."\"\n");
			return FALSE;
		}
		return TRUE;
	}

	function smtp_putcmd($cmd, $arg = "")
	{
		if ($arg != "") 
		{
			if($cmd=="") 
				$cmd = $arg;
			else 
				$cmd = $cmd." ".$arg;
		}
		fputs($this->sock, $cmd."\r\n");
		$this->smtp_debug("> ".$cmd."\n");
		return $this->smtp_ok();
	}

	function smtp_error($string)
	{
		$this->log_write("Error: Error occurred while ".$string.".\n");
		return FALSE;
	}

	function log_write($message)
	{
		$this->smtp_debug($message);
		if ($this->log_file == "") 
		{
			return TRUE;
		}

		$message = date("M d H:i:s ").get_current_user()."[".getmypid()."]: ".$message;
		if (!@file_exists($this->log_file) || !($fp = @fopen($this->log_file, "a"))) 
		{
			$this->smtp_debug("Warning: Cannot open log file \"".$this->log_file."\"\n");
			return FALSE;
		}

		flock($fp, LOCK_EX);
		fputs($fp, $message);
		fclose($fp);
		return TRUE;
	}

	function strip_comment($address)
	{
		$comment = "\([^()]*\)";
		while (ereg($comment, $address)) 
		{
			$address = ereg_replace($comment, "", $address);
		}
		return $address;
	}

	function get_address($address)
	{
		$address = ereg_replace("([ \t\r\n])+", "", $address);
		$address = ereg_replace("^.*<(.+)>.*$", "\1", $address);
		return $address;
	}
	
	function smtp_debug($message)
	{
		if ($this->debug) 
		{
			echo $message;
		}
	}
}
?>
